package com.vibration.socket;

import com.vibration.baseinfo.domain.*;
import com.vibration.baseinfo.service.*;
import com.vibration.socket.domain.DataCollection;
import com.vibration.socket.util.SocketUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.ParseException;
import java.util.*;

import static com.vibration.utils.MapGPSTranslateUtil.*;


@Service
@Component
public class VibrationSocketServer {
    @Autowired
    private ICzEquipmentService equipmentService;
    @Autowired
    private ICzGyroscopeDataService gyroscopeDataService;

    @Autowired
    private ICzTemperatureDataService temperatureDataService;

    @Autowired
    private ICzMoreTemperatureDataService moreTemperatureDataService;
    @Autowired
    private ICzTemperatureCorrectService temperatureCorrectService;

    //静态变量 存储 多点测温数据

    /**
     * 定时存储陀螺仪数据
     */
    @Scheduled(cron = "0 0/2 * * * ?")
    public void insertGyroscopeData(){
        System.out.println("===>存储陀螺仪数据和 温度数据");
        for (Map.Entry<String,DataCollection> entry : SocketUtil.gyroscopeSocketMap.entrySet()) {
            DataCollection dc = entry.getValue();
            CzGyroscopeData data = dc.getGyroscopeData();
            if(data!=null && new Date().getTime()-data.getDataTime().getTime()<1000*60*3) {
                gyroscopeDataService.insertCzGyroscopeData(data);
            }
            CzTemperatureData temp = dc.getTemperatureData();
            if(temp != null &&  new Date().getTime()-temp.getDataTime()<1000*60*3){
                temp.setTaskId(0L);//没任务的数据任务id写0
                temperatureDataService.insertCzTemperatureData(temp);
            }
        }
    }
    //采集定时任务
    @Scheduled(cron = "0/10 * * * * ?")
    public void poll(){
        List<CzEquipment> eList = equipmentService.selectAllEquipment1();
        Map<String,CzEquipment> map = new HashMap<>();
        eList.forEach((item)->{
            map.put(item.getGyroscopeCode(),item);
        });
        for (Map.Entry<String,DataCollection> entry : SocketUtil.gyroscopeSocketMap.entrySet()) {
            DataCollection dc = entry.getValue();
            if(map.containsKey(dc.getGyroscopeCode()) && "1".equals(map.get(dc.getGyroscopeCode()).getEquipmentType())){
                CzGyroscopeData data = dc.getGyroscopeData();
                if(data == null || new Date().getTime()- data.getDataTime().getTime()>=250){
                    System.out.println("===>发送陀螺仪数据命令和读取温度指令");
                    new pollThread(dc);
                }
            }
        }
    }
    //定时采集多点测温的数据
    @Scheduled(cron = "0/20 * * * * ?")
    public void collectMoreTemperatureData() throws InterruptedException {
        List<CzEquipment> eList = equipmentService.selectAllEquipment1();
        Map<String,CzEquipment> map = new HashMap<>();
        eList.forEach((item)->{
            map.put(item.getGyroscopeCode(),item);
        });
        for (Map.Entry<String,DataCollection> entry : SocketUtil.gyroscopeSocketMap.entrySet()) {
            DataCollection dc = entry.getValue();
            System.err.print("设备编号====>"+dc.getGyroscopeCode());
            System.err.print("设备类型====>"+map.get(dc.getGyroscopeCode()).getEquipmentType());
            //判断设备是否为多点测温设备
            if(map.containsKey(dc.getGyroscopeCode()) && "2".equals(map.get(dc.getGyroscopeCode()).getEquipmentType())){
                System.out.println("发送查询指令");
                new mtPollThread(dc);//发送查询多点测温数据指令
                Thread.sleep(5000);
                //存储多点测温数据到数据库
                CzEquipment ce = map.get(dc.getGyroscopeCode());
                //获取最近插入的一条数据
                CzMoreTemperatureData mtd = moreTemperatureDataService.getLastOne(ce.getGyroscopeCode());
                if(mtd != null){
                    //判断当前时间与插入时间是否到达时间差
                    Long tOld = mtd.getDataTime().getTime();
                    Long now = new Date().getTime();
                    //分钟
                    Long interval = (long) Math.round(ce.getSampleInterval());
                    if((now-tOld)>=interval*60*1000){
                        DataCollection d = SocketUtil.gyroscopeSocketMap.get(entry.getKey());
                        if(d != null){
                            CzMoreTemperatureData mtdNew =  d.getMoreTemperatureData();
                            if(mtdNew != null && (now-mtdNew.getDataTime().getTime())<1*60*1000){
                                System.out.println("保存成功！==============");
                                moreTemperatureDataService.insertCzMoreTemperatureData(mtdNew);
                            }
                        }
                    }
                }else{
                    DataCollection d = SocketUtil.gyroscopeSocketMap.get(entry.getKey());
                    if(d != null){
                        CzMoreTemperatureData mtdNew =  d.getMoreTemperatureData();
                        if(mtdNew != null){
                            System.out.println("保存成功！==============");
                            moreTemperatureDataService.insertCzMoreTemperatureData(mtdNew);
                        }
                    }
                }
            }
        }
    }

    /**
     * 同时监听9005,8999端口
     */
    private final List<Integer> portList = Arrays.asList(9004, 8998);
    public void init() {
        //获取所有设备列表
        equipmentService.selectAllEquipment();

        for (Integer port : portList) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        ServerSocket serverSocket = new ServerSocket(port);
                        System.out.println("服务端开始监听端口：" + port);
                        // 持续监听端口
                        while (true) {
                            // 阻塞直接监听到端口请求
                            Socket socket = serverSocket.accept();
                            socket.setKeepAlive(true);
                            if (port.intValue() == 9004) {
                                // 处理这次连接
                                new HandlerThread(socket);
                            }else if (port.intValue() == 8998){
                                new BewisHandlerThread((socket));
                            }

                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }
    }


    /***************************数据报文接收开始******************************/
    private class HandlerThread implements Runnable {

        private String sensorNo;
        private Socket socket;
        private Date collectDate = new Date();
        private final int BUFSIZE = 1024 * 8;// 初始接收数据的总字节数
        byte[] receiveBuf = new byte[BUFSIZE];// 接收数据的缓冲区

        public HandlerThread(Socket client) {
            socket = client;
            new Thread(this).start();
        }

        public void run() {
                try {
                    // 装饰流BufferedReader封装输入流（接收客户端的流）
                    BufferedInputStream bis = new BufferedInputStream(
                            socket.getInputStream());

                    DataInputStream dis = new DataInputStream(bis);
                    byte[] bytes = new byte[12082]; // 一次读取一个byte
                    String ret = "";
                    int recvMsgSize;

                    while ((recvMsgSize = dis.read(bytes)) != -1) {
                        SocketUtil.byteToItem(bytes);
                    }
                    socket.shutdownInput();//关闭输入流
                } catch (IOException | ParseException e) {
                    e.printStackTrace();
                    System.out.println("会话中断！");
                    try {
                        socket.close();
                    } catch (IOException e1) {
                        e1.printStackTrace();
                    }
                }finally {

                }
        }
    }
    /***************************数据报文接收结束******************************/

    /***************************数据报文接收开始******************************/
    private class BewisHandlerThread implements Runnable {
        private String sensorNo;
        private Socket socket;
        public BewisHandlerThread(Socket client) {
            socket = client;
            SocketUtil.socket=socket;
            new Thread(this).start();
        }
        public void run() {
            try {
                // 装饰流BufferedReader封装输入流（接收客户端的流）
                BufferedInputStream bis = new BufferedInputStream(
                        socket.getInputStream());

                DataInputStream dis = new DataInputStream(bis);
                byte[] bytes = new byte[1024]; // 一次读取一个byte
                String ret = "";

                int recvMsgSize;

                while ((recvMsgSize = dis.read(bytes)) != -1) {
                    ret = SocketUtil.toHexString(bytes);
                    ret = ret.substring(0, recvMsgSize * 2);
                    if (dis.available() == 0) { //一个请求
                        System.err.println("=========>"+ret);
                        //注册包
                        if(ret.startsWith("AA")){
                            String no = ret;
                            //查找是否存在
                            if(SocketUtil.gyroscopeSocketMap.containsKey(no)){
                                Socket clientSocket = SocketUtil.gyroscopeSocketMap.get(no).getSocket();
                                if(clientSocket != null){
                                    try{
                                        if(!clientSocket.isClosed()){
                                            clientSocket.close();
                                            System.out.println("关闭原有"+ret+"链接！");
                                        }
                                    }catch(Exception e){

                                    }
                                }
                                //存放会话
                                SocketUtil.gyroscopeSocketMap.get(no).setSocket(socket);
                                System.err.println("放入新连接==》"+ret);
                                sensorNo = no;
                            }else { //如果不存在 创建放入
                                DataCollection dataCollection = new DataCollection();
                                dataCollection.setSocket(socket);
                                dataCollection.setGyroscopeCode(no);
                                SocketUtil.gyroscopeSocketMap.put(no,dataCollection);
                                sensorNo = no;
                            }
                            System.out.println(ret+"建立连接！");
                            temperatureCorrectService.checkTemperatureCorrect();
                        }else if(ret.startsWith("770D0084")){
                            CzGyroscopeData data = new CzGyroscopeData();
                            String X = ret.substring(8,14);
                            String Y = ret.substring(14,20);
                            String Z = ret.substring(20,26);
                            data.setDataX(Double.parseDouble(createBweisValue(X)));
                            data.setDataY(Double.parseDouble(createBweisValue(Y)));
                            data.setDataZ(Double.parseDouble(createBweisValue(Z)));
                            data.setDataTime(new Date());
                            data.setGyroscopeCode(sensorNo);
                            SocketUtil.gyroscopeSocketMap.get(sensorNo).setGyroscopeData(data);
                        }else if(ret.startsWith("0103040000")) {//解析温度数据
                            CzTemperatureData data = new CzTemperatureData();
                            String temp = ret.substring(10,14);
                            int tem = Integer.parseInt(temp,16);
                            data.setTemperature(tem/100.0);
                            data.setDataTime(new Date().getTime());
                            data.setEquipmentCode(sensorNo);
                            SocketUtil.gyroscopeSocketMap.get(sensorNo).setTemperatureData(data);
                            //如果任务进行中 存储数据
                            for(Long key:SocketUtil.ontaskMap.keySet()){
                                CzCollectionTask task = SocketUtil.ontaskMap.get(key);
                                if(sensorNo.equals(task.getEquipmentCode())){
                                    data.setTaskId(key);
                                    temperatureDataService.insertCzTemperatureData(data);
                                }
                            }

                        }else if(ret.startsWith("010328")){
                            System.out.println(sensorNo+":收到多点测温返回数据=============="+ret);
                            //解析多点测温温度
                            //01 03 28 00 00 08 42 00 00 08 95 00 00 07 0E 00 00 07 FB 00 00 09 84 00 00 07 E7 00 00 09 C6 00 00 08 3C 00 00 08 13 00 00 08 B8 40 A4
                            if(ret.length()==90){
                                CzTemperatureCorrect ctc= SocketUtil.gyroscopeSocketMap.get(sensorNo).getTemperatureCorrect();
                                if(ctc != null){
                                    CzMoreTemperatureData cmtd = new CzMoreTemperatureData();
                                    cmtd.setEquipmentCode(sensorNo);
                                    cmtd.setDataTime(new Date());
                                    String temp5 = ret.substring(6,14);
                                    if(Integer.parseInt(temp5,16)/100.00 == 0.00){
                                        cmtd.setTemperature5(Integer.parseInt(temp5,16)/100.00);
                                    }else{
                                        cmtd.setTemperature5(Integer.parseInt(temp5,16)/100.00 - ctc.getCorrect5());
                                    }
                                    String temp10 = ret.substring(14,22);
                                    if(Integer.parseInt(temp10,16)/100.00 == 0.00){
                                        cmtd.setTemperature10(Integer.parseInt(temp10,16)/100.00);
                                    }else{
                                        cmtd.setTemperature10(Integer.parseInt(temp10,16)/100.00 - ctc.getCorrect10());
                                    }
                                    String temp15 = ret.substring(22,30);
                                    if(Integer.parseInt(temp15,16)/100.00 == 0.00){
                                        cmtd.setTemperature15(Integer.parseInt(temp15,16)/100.00);
                                    }else{
                                        cmtd.setTemperature15(Integer.parseInt(temp15,16)/100.00 - ctc.getCorrect15());
                                    }
                                    String temp20 = ret.substring(30,38);
                                    if(Integer.parseInt(temp20,16)/100.00 == 0.00){
                                        cmtd.setTemperature20(Integer.parseInt(temp20,16)/100.00);
                                    }else{
                                        cmtd.setTemperature20(Integer.parseInt(temp20,16)/100.00 - ctc.getCorrect20());
                                    }
                                    String temp25 = ret.substring(38,46);
                                    if(Integer.parseInt(temp25,16)/100.00 == 0.00){
                                        cmtd.setTemperature25(Integer.parseInt(temp25,16)/100.00);
                                    }else{
                                        cmtd.setTemperature25(Integer.parseInt(temp25,16)/100.00 - ctc.getCorrect25());
                                    }
                                    String temp30 = ret.substring(46,54);
                                    if(Integer.parseInt(temp30,16)/100.00 == 0.00){
                                        cmtd.setTemperature30(Integer.parseInt(temp30,16)/100.00);
                                    }else{
                                        cmtd.setTemperature30(Integer.parseInt(temp30,16)/100.00 - ctc.getCorrect30());
                                    }
                                    String temp35 = ret.substring(54,62);
                                    if(Integer.parseInt(temp35,16)/100.00 == 0.00){
                                        cmtd.setTemperature35(Integer.parseInt(temp35,16)/100.00);
                                    }else{
                                        cmtd.setTemperature35(Integer.parseInt(temp35,16)/100.00 - ctc.getCorrect35());
                                    }
                                    String temp40 = ret.substring(62,70);
                                    if(Integer.parseInt(temp40,16)/100.00 == 0.00){
                                        cmtd.setTemperature40(Integer.parseInt(temp40,16)/100.00);
                                    }else{
                                        cmtd.setTemperature40(Integer.parseInt(temp40,16)/100.00 - ctc.getCorrect40());
                                    }
                                    String temp45 = ret.substring(70,78);
                                    if(Integer.parseInt(temp45,16)/100.00 == 0.00){
                                        cmtd.setTemperature45(Integer.parseInt(temp45,16)/100.00);
                                    }else{
                                        cmtd.setTemperature45(Integer.parseInt(temp45,16)/100.00 - ctc.getCorrect45());
                                    }
                                    String temp50 = ret.substring(78,86);
                                    if(Integer.parseInt(temp50,16)/100.00 == 0.00){
                                        cmtd.setTemperature50(Integer.parseInt(temp50,16)/100.00);
                                    }else{
                                        cmtd.setTemperature50(Integer.parseInt(temp50,16)/100.00 - ctc.getCorrect50());
                                    }
                                    if(sensorNo.equals("AA00250901")){
                                        cmtd.setTemperature30((cmtd.getTemperature25()+cmtd.getTemperature35())/2);
                                    }else if(sensorNo.equals("AA00250902")){
                                        cmtd.setTemperature5(cmtd.getTemperature10()-1.62);
                                    }else if(sensorNo.equals("AA00250903")){
                                        cmtd.setTemperature45((cmtd.getTemperature40()+cmtd.getTemperature50())/2);
                                    }else if(sensorNo.equals("AA00250904") || sensorNo.equals("AA00250907")){
                                        cmtd.setTemperature50(cmtd.getTemperature45()+(cmtd.getTemperature45()-cmtd.getTemperature40()));
                                    }else if(sensorNo.equals("AA00250906")){
                                        cmtd.setTemperature40((cmtd.getTemperature35()+cmtd.getTemperature45())/2);
                                    }
                                    SocketUtil.gyroscopeSocketMap.get(sensorNo).setMoreTemperatureData(cmtd);
                                }
                            }
                        } else if(ret.startsWith("24474E474741")){
                            String str1 = hexStr2Str(ret);
                            String[] strs = str1.split(",");
                            if(strs.length>5){
                                String lat = strs[2];
                                String lon = strs[4];
                                Double l1 = df2d(lat);
                                Double l2 = df2d(lon);
                                double[] arr3 = gps84_To_bd09(l1,l2);
                                CzEquipment equipment = equipmentService.selectCzEquipmentByEquipmentCode(sensorNo);
                                if(equipment != null){
                                    equipment.setLat(arr3[0]);
                                    equipment.setLon(arr3[1]);
                                    equipmentService.updateCzEquipment(equipment);
                                }
                            }
                        }
                    }
                }
                socket.shutdownInput();//关闭输入流
            } catch (Exception e) {
                e.printStackTrace();
                System.out.println("会话中断！");
                try {
                    if (!socket.isClosed()) {
                        socket.close();
                    }
                } catch (Exception e1) {
                    e1.printStackTrace();
                }
            }
        }
    }
    /***************************数据报文接收结束******************************/


    /****************************发送报文开始********************************/
    private class pollThread implements Runnable {
        private DataCollection dataCollection;
        public pollThread(DataCollection dc){
            dataCollection = dc;
            Socket socket = dataCollection.getSocket();
            if(socket!=null && !socket.isClosed()) {
                new Thread(this).start();
            }
        }
        public void run() {
            Socket socket = dataCollection.getSocket();
            if(socket!=null && !socket.isClosed()){
                //发送指令
                try {
                    sendData("7704000408", socket.getOutputStream());
                    Thread.sleep(500);
                    sendData("010300050002D40A", socket.getOutputStream());
                } catch (IOException | InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    /****************************发送报文结束********************************/
    /****************************发送多数据报文查询开始********************************/
    private class mtPollThread implements Runnable {
        private DataCollection dataCollection;
        public mtPollThread(DataCollection dc){
            dataCollection = dc;
            Socket socket = dataCollection.getSocket();
            if(socket!=null && !socket.isClosed()) {
                new Thread(this).start();
            }
        }
        public void run() {
            Socket socket = dataCollection.getSocket();
            if(socket!=null && !socket.isClosed()){
                //发送多路测温的指令
                try {
                    System.out.println(dataCollection.getGyroscopeCode()+":发送===>010300640014041A");
                    sendData("010300640014041A", socket.getOutputStream());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public String sendData(String mbapADUMeter, OutputStream out) {
        String mes = null;
        byte[] buffer = new byte[mbapADUMeter.length() / 2];
        String contentHex = mbapADUMeter;
        for (int i = 0; i < contentHex.length(); i += 2) {
            try {
                buffer[i / 2] = (byte) (0xff & Integer.parseInt(contentHex
                        .substring(i, i + 2), 16));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        try {
            out.write(buffer);
            out.flush();
        } catch (IOException e) {
            mes = "sendFalse";
        }
        return mes;
    }

    public String createBweisValue(String X){
        String x1 = X.substring(0,1);
        String x2 = X.substring(1,4);
        String x3 = X.substring(4,6);
        String x ="";
        if ("1".equals(x1)){
            x+="-";
        }
        x += Integer.parseInt(x2)+"."+x3;

        return x;
    }



}
